<template>
  <div class="goods">
    <div class="wrap">
      <Crumb> </Crumb>
      <img src="../assets/img/banner.4c6b6225.png" width="100%" alt="" />
      <ul class="options">
        <li>
          <strong>排序：</strong>
          <span
            :class="index == options1Index && 'active'"
            v-for="(item, index) in options1"
            :key="index"
            @click="shopPriceFilter(item.min, item.max, index)"
            >{{ item.txt }}</span
          >
        </li>
        <li>
          <strong>分类：</strong>
          <span
            :class="index == options2Index && 'active'"
            v-for="(item, index) in options2"
            :key="index"
            @click="shopTypeFilter(item.type, index)"
            >{{ item.txt }}</span
          >
        </li>
      </ul>
      <List :arr="needLoadingList" />
      <div class="loadingico">
        {{ isReachBottom ? "已经全部加载完啦~" : "正在加载中" }}
        <i class="iconfont icon-loading" v-show="!isReachBottom"></i>
      </div>
    </div>
  </div>
</template>                            
<script>
import Crumb from "../components/Crumb.vue";
import List from "../components/home/List.vue";
import { productsSearchApi } from "@/request/api";
import {
  getScrollTop,
  getClientHeight,
  getScrollHeight,
} from "@/utils/verifyPhone";
export default {
  data() {
    return {
      // 栏目 目前可提供的参数是 1->精品推荐 2-> 热门兑换 0->全部
      did: 0,
      // ( 1->实体商品 2->虚拟商品 0->全部 )
      type: 0,
      // 大于多少积分，最少是0
      min: 0,
      // 少于多少积分，最多是10000，当传入0的时候，会直接返回所有商品，无视后台逻辑。
      max: 0,
      // 商品关键词
      keyword: "",
      // 商品列表数组
      goodsList: [],
      // 排序的数组项
      options1: [
        { min: 0, max: 0, txt: "全部" },
        // "我还可以兑换"的max值是Header组件的coin值
        { min: 0, max: 0, txt: "我还可以兑换" },
        { min: 0, max: 500, txt: "0-500分" },
        { min: 500, max: 1000, txt: "500-1000分" },
        { min: 1000, max: 1500, txt: "1000-1500分" },
        { min: 1500, max: 2500, txt: "1500-2500分" },
        { min: 2500, max: 6500, txt: "2500-6500分" },
        { min: 6500, max: 10000, txt: "6500-10000分" },
      ],
      // 排序当前项
      options1Index: 0,
      // 分类数组项
      options2: [
        { type: 0, txt: "全部" },
        { type: 1, txt: "实体商品" },
        { type: 2, txt: "虚拟商品" },
      ],
      // 分类当前项
      options2Index: 0,
      // 筛选后，按需显示出来的数据
      needLoadingList: [],
      // 商品页数
      page: 1,
      // 每页商品的条目数
      size: 8,
      //是否正在加载数据的状态
      isLoading: false,
      //是否加载完毕 (是否到达底部)
      isReachBottom: false,
    };
  },
  methods: {
    async getProductsSearch() {
      const productsSearchRes = await productsSearchApi({
        did: this.did,
        type: this.type,
        min: this.min,
        max: this.max,
        keyword: this.keyword,
      });
      if (!productsSearchRes.code == 0) return;
      console.log({ productsSearchRes });
      this.goodsList = productsSearchRes.data;
      // 初始化：展示商品数据 8 项
      this.needLoadingList = this.goodsList.filter((item, index) => index < 8);
      //初始化：默认加载第一页
      //（重现bug方式： 刷新页面，把四页数据全部加载完毕，切换到 “实体商品”，发现滚动加载时请求第五页的数据了）
      this.page = 1;
      //初始化 判断是否加载完毕
      //（重现bug方式：刷新页面，加载第两页数据，切换到“虚拟商品”，发现状态提示仍是加载中...）
      // 初始化数据，解决 bug
      this.isReachBottom = false;
      if (this.needLoadingList.length == this.goodsList.length) {
        this.isReachBottom = true;
        return;
      }
    },
    // 价格筛选商品
    shopPriceFilter(min, max, idx) {
      this.min = min;
      this.max = max;
      this.options1Index = idx;
      this.getProductsSearch();
    },
    // 分类筛选商品
    shopTypeFilter(type, indx) {
      this.type = type;
      this.options2Index = indx;
      this.getProductsSearch();
    },
  },
  created() {
    //获取关键字参数
    this.keyword = this.$route.query.keyword || ""; // 不知道有啥用的 "",不加效果也一样
    this.getProductsSearch();
  },
  // 在 dom 挂载完时才能拿到最新的 dom 绑定事件
  mounted() {
    /* 
        页码概念？滚动到一定位置时，加载下一页的数据。
        打开产品页面时，默认只加载第一页的数据（8条）
        正常情况： 每次加载下一页数据时，是往后端发起新的请求 请求某一页数据。
        积分商城：由于后端已经返回了所有数据goodsList给我们，我们今天是做一个模拟。
                 滚动到一定位置时，往goodsList获取下一页的数据。
         
        1. 默认只加载第一页的数据（8条）
        2. 先绑定滚动事件... onscroll
           mounted()        绑定事件
           beforeDestroy()  移除事件
        3. 判断滚动是否到达底部，到了准备加载下一页数据 
        4. 加载下一页
           目标：从goodsList获取下一页数据追加到goodsListShow.
           page:1 size:8 对应数组下标 0~7
           page:2 size:8 对应数组下标 8~15
           page:3 size:8 对应数组下标 16~23
           page:4 size:8 对应数组下标 24~31
           分页规律： (page-1)*size 
                      page*size-1 
                    < page*size 
             
     */
    // 滚动按需加载
    window.onscroll = () => {
      console.log("在滚了");
      // console.log(getScrollTop(), getClientHeight(), getScrollHeight());
      // 滚动高度 + 可视窗口高度 = 文档高度;  距离页底还有 200 的时候，加载更多的商品
      if (getScrollTop() + getClientHeight() < getScrollHeight() - 250) return;
      // console.log("已经到底了,可以加载下一页的数据了");
      if (this.needLoadingList.length == this.goodsList.length) {
        this.isReachBottom = true;
        return;
      }
      if (this.isLoading) return;
      //是往后端发起新的请求 (以后项目这里可能是一个请求。2s)  -- 此处setTimeout()模拟
      // 如果不写节流，只写定时器会有个 滚动一直触发 this.page++ 和 定时器的 bug，导致定时器里的函数回调执行时，页数和得到的 i 过大，goodsList 里没有这么多的的数据项，所以短路，不执行 push()

      // 把状态改为正在加载
      this.isLoading = true;
      this.page++;
      // console.log("this.page", this.page);
      setTimeout(() => {
        // console.log("触发了单次定时器");
        // 根据规律，用for循环把 goodsList的数据 逐项 push 到按需加载显示出来的数组里
        for (
          let i = (this.page - 1) * this.size;
          i < this.page * this.size;
          i++
        ) {
          // 写的 bug： this.page - 1 * this.size
          // console.log("i:", i, "page:", this.page);
          // console.log("this.goodsList[i]:", this.goodsList[i]);
          // 用短路，加个先决条件，避免 goodsList数组项空时 push undefined
          this.goodsList[i] && this.needLoadingList.push(this.goodsList[i]);
          // 执行完，把状态改为加载完成
          this.isLoading = false;
        }
      }, 1000);
    };
  },
  // 目前只能在首页搜索跳转goods页面，goods页面搜索不会跳转，所以还需要做路由监听，刷新当前页：
  watch: {
    "$route.query.keyword": {
      handler(newVal, oldVal) {
        console.log(newVal, oldVal);
        this.keyword = newVal;
        this.getProductsSearch();
      },
    },
  },
  components: {
    Crumb,
    List,
  },
};
</script>
 
<style lang = "less" scoped>
@import "../assets/css/public.less";
@base-color: #0a328e;

.goods {
  padding-bottom: 50px;
  background: #efefef;
  padding-top: 20px;
  .options {
    padding-top: 20px;
    padding-bottom: 40px;
    li {
      margin-top: 20px;
      strong {
        color: #000;
        font-weight: bold;
      }
      span {
        margin-right: 20px;
        margin-left: 10px;
        cursor: pointer;
        color: #999;
        &.active {
          color: @base-color;
          font-weight: bold;
        }
      }
    }
  }
  .loadingico {
    text-align: center;
    i {
      display: inline-block;
      animation: i 1s ease infinite;
    }
    @keyframes i {
      from {
        transform: rotate(0deg);
      }
      to {
        transform: rotate(360deg);
      }
    }
  }
}
</style>